#include<iostream>
#include<cstdio>
#include<queue>
#include<pthread.h>

#define MAX_QUEUE 5
template<class T>
class BlockQueue
{
  public:
    //初始化锁，以及队列长度
    BlockQueue(int capacity=MAX_QUEUE):_capacity(capacity)
  {
    pthread_mutex_init(&_mutex,NULL);
    pthread_cond_init(&_cond_pro,NULL);
    pthread_cond_init(&_cond_con,NULL);
  }
    //销毁锁
    ~BlockQueue()
    {
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_pro);
      pthread_cond_destroy(&_cond_con);
    }
    //向队列中添加元素
    bool Push(const T&data)
    {
      //保证添加元素操作的原子性，先上锁
      pthread_mutex_lock(&_mutex);
      //当队列的容量满的时候，阻塞等待
      while(_capacity==q.size())
      {
        pthread_cond_wait(&_cond_pro,&_mutex);
      }
      q.push(data);
      //唤醒消费者
      pthread_cond_signal(&_cond_con);
      //解锁
      pthread_mutex_unlock(&_mutex);
    }
    //从队列中删除元素
    bool Pop(T*data)
    {
      //上锁
      pthread_mutex_lock(&_mutex);
      //当队列为空时，阻塞等待
      while(q.empty())
      {
        pthread_cond_wait(&_cond_con,&_mutex);
      }
      //返回队列中第一个元素
      *data=q.front();
      q.pop();
      //唤醒生产者
      pthread_cond_signal(&_cond_pro);
      //解锁
      pthread_mutex_unlock(&_mutex);
    }
  private:
    std::queue<T> q;
    pthread_mutex_t _mutex;    //定义互斥锁
    pthread_cond_t _cond_pro;  //定义生产者条件变量
    pthread_cond_t _cond_con;  //定义消费者条件变量
    int _capacity;
};
#define MAX_USER 4
//消费者运行函数
void *consumer(void *arg)
{
  BlockQueue<int> *q=(BlockQueue<int>*)arg;
  while(1)
  {
    int data;
    q->Pop(&data);
    printf("------%p thread get data:%d\n",pthread_self(),data);
  }
  return NULL;
}
//生产者运行函数
void *productor(void *arg)
{
  BlockQueue<int>*q=(BlockQueue<int>*)arg;
  int data=0;
  while(1)
  {
    q->Push(data);
    printf("++++++%p thread put data:%d\n",pthread_self(),data++);
  }
  return NULL;
}
int main()
{
  BlockQueue<int> q;
  pthread_t con_tid[MAX_USER],pro_tid[MAX_USER];
  int ret;
  //创建消费者和生产者线程
  for(int i=0;i<MAX_USER;++i)
  {
    ret=pthread_create(&con_tid[i],NULL,consumer,(void*)&q);
    if(ret!=0)
    {
      std::cout<<"pthread_create error\n";
      return -1;
    }
    ret=pthread_create(&pro_tid[i],NULL,productor,(void*)&q);
    if(ret!=0)
    {
      std::cout<<"pthread_create error\n";
      return -1;
    }
  }
  
  //等待所有线程退出
  for(int i=0;i<MAX_USER;++i)
  {
    pthread_join(con_tid[i],NULL);
    pthread_join(pro_tid[i],NULL);
  }
  return 0;
}
